﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;
using HYElectricKernel;
using HYView;

namespace HYRElectric.Equipment
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class SwitchBoxesReLayout : YJKCommandManual
	{
		protected override Result YJKExcute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
			Result result = SwitchView.SetUsableView((HYView.CmdViewType)17, cmdData);
			if (result != Result.Succeeded)
			{
				return result;
			}
			this.m_uiDoc = cmdData.Application.ActiveUIDocument;
			this.m_doc = this.m_uiDoc.Document;
			this.m_form = new SwitchBoxesReLayoutForm();
			this.m_form.Show(WindowHelper.HWndRevit);
			WindowHelper.SendMessageToWndRevit();
			this.m_lstDocElecEquips = SwitchBoxesReLayout.GetElecEqupsByDoc(this.m_doc);
			for (;;)
			{
				try
				{
					IList<Reference> lstRefEquips = this.m_uiDoc.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new ElectricSwitchBoxesFilter(), "请选择配电柜：");
					List<FamilyInstance> equipsByRef = this.GetEquipsByRef(lstRefEquips);
					if (equipsByRef.Count != 0)
					{
						Transaction transaction = new Transaction(this.m_doc, "DelSwitchBoxesOper");
						try
						{
							transaction.Start();
							foreach (FamilyInstance familyInstance in equipsByRef)
							{
								SwitchBoxesReLayout.EquipInfo equipInfo = new SwitchBoxesReLayout.EquipInfo(familyInstance);
								List<SwitchBoxesReLayout.EquipInfo> groupEquips = equipInfo.GetGroupEquips(this.m_lstDocElecEquips);
								if (groupEquips.Count > 1 && (this.m_form.ReLayEquip || this.m_form.ReLabelEquip))
								{
									int num = groupEquips.IndexOf(equipInfo);
									if (num > -1 && num != groupEquips.Count - 1)
									{
										int num2 = 0;
										if (this.m_form.ReLabelEquip)
										{
											SwitchBoxesReLayout.EquipInfo equipInfo2 = groupEquips[num + 1];
											if (equipInfo.LabelIdx < equipInfo2.LabelIdx)
											{
												num2 = -1;
											}
											else if (equipInfo.LabelIdx > equipInfo2.LabelIdx)
											{
												num2 = 1;
											}
										}
										XYZ xyz = equipInfo.Direction.Negate() * equipInfo.Width;
										for (int i = num + 1; i < groupEquips.Count; i++)
										{
											SwitchBoxesReLayout.EquipInfo equipInfo3 = groupEquips[i];
											if (this.m_form.ReLabelEquip)
											{
												FamilyInstance familyInstance2 = this.m_doc.GetElement(equipInfo3.ElemID) as FamilyInstance;
												if (familyInstance2 != null)
												{
													string text = equipInfo3.Prefix;
													int num3 = equipInfo3.LabelIdx + num2;
													text += num3;
													familyInstance2.GetParameter(BuiltInParameter.RBS_ELEC_PANEL_NAME).Set(text);
													equipInfo3.LabelIdx = num3;
												}
											}
											if (this.m_form.ReLayEquip)
											{
												equipInfo3.Position += xyz;
												((this.m_doc.GetElement(equipInfo3.ElemID) as FamilyInstance).Location as LocationPoint).Point = equipInfo3.Position;
											}
										}
									}
								}
								this.m_lstDocElecEquips.Remove(equipInfo);
								this.m_doc.Delete(familyInstance.Id);
							}
							transaction.Commit();
						}
						catch (Exception)
						{
							transaction.RollBack();
							this.m_form.Close();
							return Autodesk.Revit.UI.Result.Succeeded;
						}
						continue;
					}
				}
				catch (Exception)
				{
					this.m_form.Close();
					return Autodesk.Revit.UI.Result.Succeeded;
				}
				break;
			}
			this.m_form.Close();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		internal static List<SwitchBoxesReLayout.EquipInfo> GetAdjoinEquipsGroup(FamilyInstance fiEquip, Document doc)
		{
			List<SwitchBoxesReLayout.EquipInfo> elecEqupsByDoc = SwitchBoxesReLayout.GetElecEqupsByDoc(doc);
			return new SwitchBoxesReLayout.EquipInfo(fiEquip).GetGroupEquips(elecEqupsByDoc);
		}

		private static List<SwitchBoxesReLayout.EquipInfo> GetElecEqupsByDoc(Document doc)
		{
			List<SwitchBoxesReLayout.EquipInfo> list = new List<SwitchBoxesReLayout.EquipInfo>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(FamilyInstance));
			foreach (Element element in filteredElementCollector.OfCategory(BuiltInCategory.OST_ElectricalEquipment).ToElements())
			{
				FamilyInstance familyInstance = (FamilyInstance)element;
				if (ElectricSwitchBoxesFilter.IsValidSwitchBoxes(familyInstance))
				{
					list.Add(new SwitchBoxesReLayout.EquipInfo(familyInstance));
				}
			}
			return list;
		}

		private List<FamilyInstance> GetEquipsByRef(IList<Reference> lstRefEquips)
		{
			List<FamilyInstance> list = new List<FamilyInstance>();
			foreach (Reference reference in lstRefEquips)
			{
				FamilyInstance item = this.m_doc.GetElement(reference) as FamilyInstance;
				list.Add(item);
			}
			return list;
		}

		private List<SwitchBoxesReLayout.EquipInfo> m_lstDocElecEquips;

		private SwitchBoxesReLayoutForm m_form;

		private new UIDocument m_uiDoc;

		private new Document m_doc;

		internal class EquipInfo : IEquatable<SwitchBoxesReLayout.EquipInfo>
		{
			public EquipInfo(FamilyInstance fi)
			{
				this.InitEquipData(fi);
			}

			bool IEquatable<SwitchBoxesReLayout.EquipInfo>.Equals(SwitchBoxesReLayout.EquipInfo other)
			{
				return this.ElemID == other.ElemID;
			}

			public List<SwitchBoxesReLayout.EquipInfo> GetGroupEquips(List<SwitchBoxesReLayout.EquipInfo> lstEquips)
			{
				List<SwitchBoxesReLayout.EquipInfo> list = new List<SwitchBoxesReLayout.EquipInfo>();
				this.RecursionNextEquip(this, lstEquips, ref list, false);
				list.Reverse();
				list.Add(this);
				List<SwitchBoxesReLayout.EquipInfo> collection = new List<SwitchBoxesReLayout.EquipInfo>();
				this.RecursionNextEquip(this, lstEquips, ref collection, true);
				list.AddRange(collection);
				return list;
			}

			private void SplitLabel(string strVal)
			{
				if (!string.IsNullOrEmpty(strVal))
				{
					strVal.Trim();
					int length = strVal.Length;
					int num = -1;
					for (int i = length - 1; i > -1; i--)
					{
						if (!char.IsDigit(strVal[i]))
						{
							num = i;
							break;
						}
					}
					if (num == -1)
					{
						this.m_strPrefix = "";
						this.m_nLabelIdx = Convert.ToInt32(strVal);
						return;
					}
					this.m_strPrefix = strVal.Substring(0, num + 1);
					string value = strVal.Substring(num + 1, length - num - 1);
					this.m_nLabelIdx = Convert.ToInt32(value);
				}
			}

			private void InitEquipData(FamilyInstance fi)
			{
				this.m_idEquip = fi.Id;
				Transform transform = fi.GetTransform();
				this.m_ptPosition = transform.Origin;
				this.m_vtDirection = transform.BasisX;
				this.m_dWidth = fi.GetParameter(SwitchBoxesLayout.m_strKeyX).AsDouble();
				this.m_dThickness = fi.GetParameter(SwitchBoxesLayout.m_strKeyY).AsDouble();
				string strVal = "";
				try
				{
					strVal = fi.GetParameter(BuiltInParameter.RBS_ELEC_PANEL_NAME).AsString();
				}
				catch
				{
				}
				this.SplitLabel(strVal);
			}

			private Curve CreateEdge(bool bLeft = true)
			{
				XYZ xyz = this.Position;
				if (!bLeft)
				{
					xyz += this.m_vtDirection * this.m_dWidth;
				}
				XYZ xyz2 = XYZ.BasisZ.CrossProduct(this.m_vtDirection).Normalize();
				XYZ xyz3 = xyz + xyz2 * this.m_dThickness * 0.5;
				XYZ xyz4 = xyz - xyz2 * this.m_dThickness * 0.5;
				return Line.CreateBound(xyz3, xyz4);
			}

			private void RecursionNextEquip(SwitchBoxesReLayout.EquipInfo equipCur, List<SwitchBoxesReLayout.EquipInfo> lstEquips, ref List<SwitchBoxesReLayout.EquipInfo> lstResult, bool bNext = true)
			{
				Curve curve = equipCur.CreateEdge(!bNext);
				if (curve == null)
				{
					return;
				}
				XYZ endPoint = curve.GetEndPoint(0);
				XYZ endPoint2 = curve.GetEndPoint(1);
				foreach (SwitchBoxesReLayout.EquipInfo equipInfo in lstEquips)
				{
					if (!(equipCur.ElemID == equipInfo.ElemID) && equipCur.Prefix.CompareTo(equipInfo.Prefix) == 0 && GeoUtil.IsEqual(equipCur.Elev, equipInfo.Elev))
					{
						Curve curve2 = equipInfo.CreateEdge(bNext);
						if (curve2 == null)
						{
							break;
						}
						XYZ endPoint3 = curve2.GetEndPoint(0);
						XYZ endPoint4 = curve2.GetEndPoint(1);
						XYZ xyz = null;
						XYZ xyz2 = null;
						Geometry.OverlapType overlapType = Geometry.IsOverlapOfTwoLine(endPoint, endPoint2, endPoint3, endPoint4, ref xyz, ref xyz2, SwitchBoxesReLayout.EquipInfo.m_dEpsilon);
						if (overlapType != Geometry.OverlapType._OT_None && overlapType != Geometry.OverlapType._OT_Linked && !lstResult.Contains(equipInfo))
						{
							lstResult.Add(equipInfo);
							this.RecursionNextEquip(equipInfo, lstEquips, ref lstResult, bNext);
							break;
						}
					}
				}
			}

			public XYZ Position
			{
				get
				{
					return this.m_ptPosition;
				}
				set
				{
					this.m_ptPosition = value;
				}
			}

			public XYZ Direction
			{
				get
				{
					return this.m_vtDirection;
				}
			}

			public double Elev
			{
				get
				{
					return this.m_ptPosition.Z;
				}
			}

			public ElementId ElemID
			{
				get
				{
					return this.m_idEquip;
				}
			}

			public double Width
			{
				get
				{
					return this.m_dWidth;
				}
			}

			public double Thickness
			{
				get
				{
					return this.m_dThickness;
				}
			}

			public string Prefix
			{
				get
				{
					return this.m_strPrefix;
				}
			}

			public int LabelIdx
			{
				get
				{
					return this.m_nLabelIdx;
				}
				set
				{
					this.m_nLabelIdx = value;
				}
			}

			private ElementId m_idEquip;

			private XYZ m_ptPosition;

			private XYZ m_vtDirection;

			private double m_dElev;

			private double m_dWidth;

			private double m_dThickness;

			private string m_strPrefix = "";

			private int m_nLabelIdx;

			public static double m_dEpsilon = 1E-06;
		}
	}
}
